// webgl/webgl_interactive_cubes_gpu.js
import {document,window,requestAnimationFrame,cancelAnimationFrame,Event,core,performance} from 'dhtml-weixin';
import * as THREE from '../three/Three.js';
import Stats from './jsm/libs/stats.module.js';

import { TrackballControls } from './jsm/controls/TrackballControls.js';
import * as BufferGeometryUtils from './jsm/utils/BufferGeometryUtils.js';
var requestId
Page({
	   
         onUnload() {
	   		cancelAnimationFrame(requestId, this.canvas)
this.worker && this.worker.terminate()
		setTimeout(() => {
			if (this.renderer instanceof THREE.WebGLRenderer) {
				this.renderer.dispose()
				this.renderer.forceContextLoss()
				this.renderer.context = null
				this.renderer.domElement = null
				this.renderer = null
			}
		}, 0)
        
	},
         webgl_touch(e) {
        const web_e = Event.fix(e)
        //window.dispatchEvent(web_e)
        //document.dispatchEvent(web_e)
        this.canvas.dispatchEvent(web_e)
    },
async onLoad() {
        const canvas3d = this.canvas =await document.createElementAsync("canvas","webgl")
var that = this

        let container, stats;
        let camera, controls, scene, renderer;
        let pickingTexture, pickingScene;
        let highlightBox;

        const pickingData = [];

        const pointer = new THREE.Vector2();
        const offset = new THREE.Vector3( 10, 10, 10 );

        init();
        animate();

        function init() {

            container = document.getElementById( 'container' );

            camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
            camera.position.z = 1000;

            scene = new THREE.Scene();
            scene.background = new THREE.Color( 0xffffff );

            pickingScene = new THREE.Scene();
            pickingTexture = new THREE.WebGLRenderTarget( 1, 1 );

            scene.add( new THREE.AmbientLight( 0x555555 ) );

            const light = new THREE.SpotLight( 0xffffff, 1.5 );
            light.position.set( 0, 500, 2000 );
            scene.add( light );

            const pickingMaterial = new THREE.MeshBasicMaterial( { vertexColors: true } );
            const defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true, vertexColors: true, shininess: 0	} );

            function applyVertexColors( geometry, color ) {

                const position = geometry.attributes.position;
                const colors = [];

                for ( let i = 0; i < position.count; i ++ ) {

                    colors.push( color.r, color.g, color.b );

                }

                geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );

            }

            const geometriesDrawn = [];
            const geometriesPicking = [];

            const matrix = new THREE.Matrix4();
            const quaternion = new THREE.Quaternion();
            const color = new THREE.Color();

            for ( let i = 0; i < 5000; i ++ ) {

                let geometry = new THREE.BoxGeometry();

                const position = new THREE.Vector3();
                position.x = Math.random() * 10000 - 5000;
                position.y = Math.random() * 6000 - 3000;
                position.z = Math.random() * 8000 - 4000;

                const rotation = new THREE.Euler();
                rotation.x = Math.random() * 2 * Math.PI;
                rotation.y = Math.random() * 2 * Math.PI;
                rotation.z = Math.random() * 2 * Math.PI;

                const scale = new THREE.Vector3();
                scale.x = Math.random() * 200 + 100;
                scale.y = Math.random() * 200 + 100;
                scale.z = Math.random() * 200 + 100;

                quaternion.setFromEuler( rotation );
                matrix.compose( position, quaternion, scale );

                geometry.applyMatrix4( matrix );

                // give the geometry's vertices a random color, to be displayed

                applyVertexColors( geometry, color.setHex( Math.random() * 0xffffff ) );

                geometriesDrawn.push( geometry );

                geometry = geometry.clone();

                // give the geometry's vertices a color corresponding to the "id"

                applyVertexColors( geometry, color.setHex( i ) );

                geometriesPicking.push( geometry );

                pickingData[ i ] = {

                    position: position,
                    rotation: rotation,
                    scale: scale

                };

            }

            const objects = new THREE.Mesh( BufferGeometryUtils.mergeBufferGeometries( geometriesDrawn ), defaultMaterial );
            scene.add( objects );

            pickingScene.add( new THREE.Mesh( BufferGeometryUtils.mergeBufferGeometries( geometriesPicking ), pickingMaterial ) );

            highlightBox = new THREE.Mesh(
                new THREE.BoxGeometry(),
                new THREE.MeshLambertMaterial( { color: 0xffff00 }
                ) );
            scene.add( highlightBox );

            renderer = that.renderer = new THREE.WebGLRenderer( { canvas:canvas3d,antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );

            controls = new TrackballControls( camera, renderer.domElement );
            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 1.2;
            controls.panSpeed = 0.8;
            controls.noZoom = false;
            controls.noPan = false;
            controls.staticMoving = true;
            controls.dynamicDampingFactor = 0.3;

            stats = new Stats();
            container.appendChild( stats.dom );

         //   renderer.domElement.addEventListener( 'pointermove', onPointerMove );

        }

        //

        function onPointerMove( e ) {

            pointer.x = e.clientX;
            pointer.y = e.clientY;

        }

        function animate() {

            requestId = requestAnimationFrame(animate);

            render();
            //stats.update();

        }

        function pick() {

            //render the picking scene off-screen

            // set the view offset to represent just a single pixel under the mouse

            camera.setViewOffset( renderer.domElement.width, renderer.domElement.height, pointer.x * window.devicePixelRatio | 0, pointer.y * window.devicePixelRatio | 0, 1, 1 );

            // render the scene

            renderer.setRenderTarget( pickingTexture );
            renderer.render( pickingScene, camera );

            // clear the view offset so rendering returns to normal

            camera.clearViewOffset();

            //create buffer for reading single pixel

            const pixelBuffer = new Uint8Array( 4 );

            //read the pixel

            renderer.readRenderTargetPixels( pickingTexture, 0, 0, 1, 1, pixelBuffer );

            //interpret the pixel as an ID

            const id = ( pixelBuffer[ 0 ] << 16 ) | ( pixelBuffer[ 1 ] << 8 ) | ( pixelBuffer[ 2 ] );
            const data = pickingData[ id ];

            if ( data ) {

                //move our highlightBox so that it surrounds the picked object

                if ( data.position && data.rotation && data.scale ) {

                    highlightBox.position.copy( data.position );
                    highlightBox.rotation.copy( data.rotation );
                    highlightBox.scale.copy( data.scale ).add( offset );
                    highlightBox.visible = true;

                }

            } else {

                highlightBox.visible = false;

            }

        }

        function render() {

            controls.update();

            pick();

            renderer.setRenderTarget( null );
            renderer.render( scene, camera );

        }

    }
})